package helper

import (
	"fmt"
	"strings"

	"mall/service/wpgql/api/internal/graph/model"
	"mall/service/wpgql/api/internal/graph/util"
)

const (
	arrayValueSeparator    = ","
	keyValueSeparator      = ":"
	keyOpSeparator         = ","
	arrayKeyValueSeparator = ";"
)

func GetBooleanFilterMap(m *model.BooleanFilter) map[string]string { ////
	if m == nil {
		return nil
	}

	opMap := make(map[string]string)

	if m.EqualTo != nil {
		val := "0"
		if *m.EqualTo {
			val = "1"
		}
		opMap["equalTo"] = val
	}
	if m.NotEqualTo != nil {
		val := "0"
		if *m.NotEqualTo {
			val = "1"
		}
		opMap["notEqualTo"] = val
	}

	return opMap
}

func GetIDFilterMap(m *model.IDFilter) map[string]string { ////
	if m == nil {
		return nil
	}

	opMap := make(map[string]string)

	if m.EqualTo != nil {
		opMap["equalTo"] = *m.EqualTo
	}
	if m.NotEqualTo != nil {
		opMap["notEqualTo"] = *m.NotEqualTo
	}
	if len(m.In) > 0 {
		opMap["in"] = strings.Join(m.In, arrayValueSeparator)
	}
	if len(m.NotIn) > 0 {
		opMap["notIn"] = strings.Join(m.NotIn, arrayValueSeparator)
	}

	return opMap
}

func GetStringFilterMap(m *model.StringFilter) map[string]string { ////
	if m == nil {
		return nil
	}

	opMap := make(map[string]string)

	if m.EqualTo != nil {
		opMap["equalTo"] = *m.EqualTo
	}
	if m.NotEqualTo != nil {
		opMap["notEqualTo"] = *m.NotEqualTo
	}
	if len(m.In) > 0 {
		opMap["in"] = strings.Join(m.In, arrayValueSeparator)
	}
	if len(m.NotIn) > 0 {
		opMap["notIn"] = strings.Join(m.NotIn, arrayValueSeparator)
	}
	if m.StartWith != nil {
		opMap["startWith"] = *m.StartWith
	}
	if m.EndWith != nil {
		opMap["endWith"] = *m.EndWith
	}
	if m.Contain != nil {
		opMap["contain"] = *m.Contain
	}
	if m.StartWithStrict != nil {
		opMap["startWithStrict"] = *m.StartWithStrict
	}
	if m.EndWithStrict != nil {
		opMap["endWithStrict"] = *m.EndWithStrict
	}
	if m.ContainStrict != nil {
		opMap["containStrict"] = *m.ContainStrict
	}

	return opMap
}

func GetFloatFilterMap(m *model.FloatFilter) map[string]string { ////
	if m == nil {
		return nil
	}

	opMap := make(map[string]string)

	if m.EqualTo != nil {
		opMap["equalTo"] = fmt.Sprintf("%v", *m.EqualTo)
	}
	if m.NotEqualTo != nil {
		opMap["notEqualTo"] = fmt.Sprintf("%v", *m.NotEqualTo)
	}
	if m.LessThan != nil {
		opMap["lessThan"] = fmt.Sprintf("%v", *m.LessThan)
	}
	if m.LessThanOrEqualTo != nil {
		opMap["lessThanOrEqualTo"] = fmt.Sprintf("%v", *m.LessThanOrEqualTo)
	}
	if m.MoreThan != nil {
		opMap["moreThan"] = fmt.Sprintf("%v", *m.MoreThan)
	}
	if m.MoreThanOrEqualTo != nil {
		opMap["moreThanOrEqualTo"] = fmt.Sprintf("%v", *m.MoreThanOrEqualTo)
	}
	if len(m.In) > 0 {
		opMap["in"] = strings.Join(util.FloatsToStrings(m.In), arrayValueSeparator)
	}
	if len(m.NotIn) > 0 {
		opMap["notIn"] = strings.Join(util.FloatsToStrings(m.NotIn), arrayValueSeparator)
	}

	return opMap
}

func GetIntFilterMap(m *model.IntFilter) map[string]string { ////
	if m == nil {
		return nil
	}

	opMap := make(map[string]string)

	if m.EqualTo != nil {
		opMap["equalTo"] = fmt.Sprintf("%v", *m.EqualTo)
	}
	if m.NotEqualTo != nil {
		opMap["notEqualTo"] = fmt.Sprintf("%v", *m.NotEqualTo)
	}
	if m.LessThan != nil {
		opMap["lessThan"] = fmt.Sprintf("%v", *m.LessThan)
	}
	if m.LessThanOrEqualTo != nil {
		opMap["lessThanOrEqualTo"] = fmt.Sprintf("%v", *m.LessThanOrEqualTo)
	}
	if m.MoreThan != nil {
		opMap["moreThan"] = fmt.Sprintf("%v", *m.MoreThan)
	}
	if m.MoreThanOrEqualTo != nil {
		opMap["moreThanOrEqualTo"] = fmt.Sprintf("%v", *m.MoreThanOrEqualTo)
	}
	if len(m.In) > 0 {
		opMap["in"] = strings.Join(util.IntsToStrings(m.In), arrayValueSeparator)
	}
	if len(m.NotIn) > 0 {
		opMap["notIn"] = strings.Join(util.IntsToStrings(m.NotIn), arrayValueSeparator)
	}

	return opMap
}

func ConnectionWhereMapToString(m map[string]map[string][]string) string { ////
	if m == nil {
		return ""
	}

	var sa []string
	for key, opMap := range m {
		for k, v := range opMap {
			s := key + keyOpSeparator + k + keyValueSeparator + strings.Join(v, arrayValueSeparator)
			sa = append(sa, s)
		}
	}

	return strings.Join(sa, arrayKeyValueSeparator)
}

func GetForumTopicConnectionSearch(search *string) string {
	if search == nil {
		return ""
	}

	return *search
}

func GetForumTopicConnectionWhere(m *model.ForumTopicConnectionWhere, rpcEntityName string) (string, string, string) {
	if m == nil {
		return "", "", ""
	}

	entitySettings, hasEntitySettings := util.RpcEntityPreloadMap[util.RpcEntityNames.ForumTopic]
	if !hasEntitySettings {
		return "", "", ""
	}

	whereMap := make(map[string]map[string][]string)

	if m.ID != nil {
		columnSetting, hasColumnSetting := entitySettings["id"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetIDFilterMap(m.ID)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}
	if m.Title != nil {
		columnSetting, hasColumnSetting := entitySettings["title"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetStringFilterMap(m.Title)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}
	if m.AuthorID != nil {
		columnSetting, hasColumnSetting := entitySettings["authorId"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetIntFilterMap(m.AuthorID)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}

	whereFilter := ConnectionWhereMapToString(whereMap)
	var preWhereEntityName string
	var preWhereFilter string

	if rpcEntityName == "" {
		if preWhereEntityName == "" && m.Author != nil {
			columnSetting, hasColumnSetting := entitySettings["author"]
			if hasColumnSetting {
				preWhereEntityName = columnSetting.RpcEntityName
				preWhereFilter, _, _ = GetForumUserConnectionWhere(m.Author, preWhereEntityName)
			}
		}
	}

	return whereFilter, preWhereEntityName, preWhereFilter
}

func GetForumTopicConnectionFilterMap(m *model.ForumTopicConnectionFilter) map[string]string {
	if m == nil {
		return nil
	}

	filterMap := make(map[string]string)

	if m.Search != nil {
		search := GetForumTopicConnectionSearch(m.Search)
		if search != "" {
			filterMap["search"] = search
		}
	}

	if m.Where != nil {
		filter, preFilterEntity, preFilter := GetForumTopicConnectionWhere(m.Where, "")
		if filter != "" {
			filterMap["filter"] = filter
		}
		if preFilterEntity != "" {
			filterMap["preFilterEntity"] = preFilterEntity
			if preFilter != "" {
				filterMap["preFilter"] = preFilter
			}
		}
	}

	return filterMap
}

func GetForumPostConnectionSearch(search *string) string {
	if search == nil {
		return ""
	}

	return *search
}

func GetForumPostConnectionWhere(m *model.ForumPostConnectionWhere, rpcEntityName string) (string, string, string) {
	if m == nil {
		return "", "", ""
	}

	entitySettings, hasEntitySettings := util.RpcEntityPreloadMap[util.RpcEntityNames.ForumPost]
	if !hasEntitySettings {
		return "", "", ""
	}

	whereMap := make(map[string]map[string][]string)

	if m.ID != nil {
		columnSetting, hasColumnSetting := entitySettings["id"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetIDFilterMap(m.ID)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}
	if m.AuthorID != nil {
		columnSetting, hasColumnSetting := entitySettings["authorId"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetIntFilterMap(m.AuthorID)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}

	whereFilter := ConnectionWhereMapToString(whereMap)
	var preWhereEntityName string
	var preWhereFilter string

	if rpcEntityName == "" {
		if preWhereEntityName == "" && m.Author != nil {
			columnSetting, hasColumnSetting := entitySettings["author"]
			if hasColumnSetting {
				preWhereEntityName = columnSetting.RpcEntityName
				preWhereFilter, _, _ = GetForumUserConnectionWhere(m.Author, preWhereEntityName)
			}
		}
		if preWhereEntityName == "" && m.Topic != nil {
			columnSetting, hasColumnSetting := entitySettings["topic"]
			if hasColumnSetting {
				preWhereEntityName = columnSetting.RpcEntityName
				preWhereFilter, _, _ = GetForumTopicConnectionWhere(m.Topic, preWhereEntityName)
			}
		}
	}

	return whereFilter, preWhereEntityName, preWhereFilter
}

func GetForumPostConnectionFilterMap(m *model.ForumPostConnectionFilter) map[string]string {
	if m == nil {
		return nil
	}

	filterMap := make(map[string]string)

	if m.Search != nil {
		search := GetForumPostConnectionSearch(m.Search)
		if search != "" {
			filterMap["search"] = search
		}
	}

	if m.Where != nil {
		filter, preFilterEntity, preFilter := GetForumPostConnectionWhere(m.Where, "")
		if filter != "" {
			filterMap["filter"] = filter
		}
		if preFilterEntity != "" {
			filterMap["preFilterEntity"] = preFilterEntity
			if preFilter != "" {
				filterMap["preFilter"] = preFilter
			}
		}
	}

	return filterMap
}

func GetForumReactionConnectionSearch(search *string) string {
	if search == nil {
		return ""
	}

	return *search
}

func GetForumReactionConnectionWhere(m *model.ForumReactionConnectionWhere, rpcEntityName string) (string, string, string) {
	if m == nil {
		return "", "", ""
	}

	entitySettings, hasEntitySettings := util.RpcEntityPreloadMap[util.RpcEntityNames.ForumReaction]
	if !hasEntitySettings {
		return "", "", ""
	}

	whereMap := make(map[string]map[string][]string)

	if m.ID != nil {
		columnSetting, hasColumnSetting := entitySettings["id"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetIDFilterMap(m.ID)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}
	if m.ReactionType != nil {
		columnSetting, hasColumnSetting := entitySettings["reactionType"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetStringFilterMap(m.ReactionType)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}
	if m.Date != nil {
		columnSetting, hasColumnSetting := entitySettings["date"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetIntFilterMap(m.Date)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}

	whereFilter := ConnectionWhereMapToString(whereMap)
	var preWhereEntityName string
	var preWhereFilter string

	if rpcEntityName == "" {
		if preWhereEntityName == "" && m.User != nil {
			columnSetting, hasColumnSetting := entitySettings["user"]
			if hasColumnSetting {
				preWhereEntityName = columnSetting.RpcEntityName
				preWhereFilter, _, _ = GetForumUserConnectionWhere(m.User, preWhereEntityName)
			}
		}
		if preWhereEntityName == "" && m.Topic != nil {
			columnSetting, hasColumnSetting := entitySettings["topic"]
			if hasColumnSetting {
				preWhereEntityName = columnSetting.RpcEntityName
				preWhereFilter, _, _ = GetForumTopicConnectionWhere(m.Topic, preWhereEntityName)
			}
		}
		if preWhereEntityName == "" && m.Post != nil {
			columnSetting, hasColumnSetting := entitySettings["post"]
			if hasColumnSetting {
				preWhereEntityName = columnSetting.RpcEntityName
				preWhereFilter, _, _ = GetForumPostConnectionWhere(m.Post, preWhereEntityName)
			}
		}
	}

	return whereFilter, preWhereEntityName, preWhereFilter
}

func GetForumReactionConnectionFilterMap(m *model.ForumReactionConnectionFilter) map[string]string {
	if m == nil {
		return nil
	}

	filterMap := make(map[string]string)

	if m.Search != nil {
		search := GetForumReactionConnectionSearch(m.Search)
		if search != "" {
			filterMap["search"] = search
		}
	}

	if m.Where != nil {
		filter, preFilterEntity, preFilter := GetForumReactionConnectionWhere(m.Where, "")
		if filter != "" {
			filterMap["filter"] = filter
		}
		if preFilterEntity != "" {
			filterMap["preFilterEntity"] = preFilterEntity
			if preFilter != "" {
				filterMap["preFilter"] = preFilter
			}
		}
	}

	return filterMap
}

func GetForumUserConnectionSearch(search *string) string { ////
	if search == nil {
		return ""
	}

	return *search
}

func GetForumUserConnectionWhere(m *model.ForumUserConnectionWhere, rpcEntityName string) (string, string, string) { ////
	if m == nil {
		return "", "", ""
	}

	entitySettings, hasEntitySettings := util.RpcEntityPreloadMap[util.RpcEntityNames.ForumUser]
	if !hasEntitySettings {
		return "", "", ""
	}

	whereMap := make(map[string]map[string][]string)

	if m.ID != nil {
		columnSetting, hasColumnSetting := entitySettings["id"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetIDFilterMap(m.ID)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}
	if m.NiceName != nil {
		columnSetting, hasColumnSetting := entitySettings["niceName"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			whereMap[columnName] = make(map[string][]string)
			opMap := GetStringFilterMap(m.NiceName)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}
	if m.DisplayName != nil {
		columnSetting, hasColumnSetting := entitySettings["displayName"]
		if hasColumnSetting {
			columnName := columnSetting.Name
			opMap := GetStringFilterMap(m.DisplayName)
			for k, v := range opMap {
				whereMap[columnName][k] = append(whereMap[columnName][k], v)
			}
		}
	}
	whereFilter := ConnectionWhereMapToString(whereMap)
	var preWhereEntityName string
	var preWhereFilter string

	if rpcEntityName == "" {
		if preWhereEntityName == "" && m.Friendships != nil {
			columnSetting, hasColumnSetting := entitySettings["friendships"]
			if hasColumnSetting {
				preWhereEntityName = columnSetting.RpcEntityName
				preWhereFilter, _, _ = GetForumFriendshipConnectionWhere(m.Friendships, preWhereEntityName)
			}
		}
		if preWhereEntityName == "" && m.Comments != nil {
			columnSetting, hasColumnSetting := entitySettings["comments"]
			if hasColumnSetting {
				preWhereEntityName = columnSetting.RpcEntityName
				preWhereFilter, _, _ = GetForumCommentConnectionWhere(m.Comments, preWhereEntityName)
			}
		}
	}

	return whereFilter, preWhereEntityName, preWhereFilter
}

func GetForumUserConnectionFilterMap(m *model.ForumUserConnectionFilter) map[string]string { ////
	if m == nil {
		return nil
	}

	filterMap := make(map[string]string)

	if m.Search != nil {
		search := GetForumUserConnectionSearch(m.Search)
		if search != "" {
			filterMap["search"] = search
		}
	}

	if m.Where != nil {
		filter, preFilterEntity, preFilter := GetForumUserConnectionWhere(m.Where, "")
		if filter != "" {
			filterMap["filter"] = filter
		}
		if preFilterEntity != "" {
			filterMap["preFilterEntity"] = preFilterEntity
			if preFilter != "" {
				filterMap["preFilter"] = preFilter
			}
		}
	}

	return filterMap
}

func GetForumFriendshipConnectionWhere(
	m *model.ForumFriendshipConnectionWhere,
	entityName string,
) (string, string, string) {
	return "", "", ""
}

func GetForumCommentConnectionWhere(
	m *model.ForumCommentConnectionWhere,
	entityName string,
) (string, string, string) {
	return "", "", ""
}
